package pprz.data_components.parsers;

import java.util.Collection;
import java.util.HashMap;
import java.util.Vector;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MessageParser extends DefaultHandler {

	static String[] cTypes=
	{
		"int8",
		"uint8",
		"int16",
		"uint16",
		"int32",
		"uint32",
		"float",
		"string",
		"uint16[]",
		"int16[]"
	};
	
	static String[] mClasses=
	{
		"telemetry",
		"datalink",
		"ground"
	};
	public class MessageField
	{
		public String name;
		public int type;
		public String unit;
		public boolean noType;
		public boolean noUnit;
		public boolean noName;
		
		public MessageField(String name, String type, String unit)
		{
			this.name=name;
			this.unit=unit;
			int i=0; while (i<cTypes.length && !cTypes[i].equalsIgnoreCase(type.trim())) i++;
			if (i<cTypes.length) this.type=i;
			else this.type=-1;
			noType=false;
			noName=false;
			noUnit=false;
		}
		public String toString()
		{
			StringBuffer s=new StringBuffer();
			s.append(name).append(" ");
			if (type>0) s.append(cTypes[type]).append(" ");
			s.append(unit).append(" ");
			return s.toString();
		}
	}
	
	public class MessageFormat
	{
		public int mId;
		public int cId;
		public String name;
		public Vector<MessageField> fields;
		public boolean noClass;
		public boolean noName;
		public boolean noId;
		public int noTypeField;
		public int noUnitField;
		public int noNameField;
		
		public MessageFormat(int cId, int mId, String name) 
		{this.cId=cId; this.mId=mId; this.name=name; fields=new Vector<MessageField>();
		noClass=false;noName=false;noId=false;noTypeField=0;noUnitField=0;noNameField=0;}

		void addField(MessageField f) {fields.add(f);}
		
		public String toString()
		{
			StringBuffer s=new StringBuffer();
			s.append(mId).append(" ");
			s.append(cId).append(" ");
			s.append(name).append(" ");
			s.append(fields.toString());
			return s.toString();
		}
	}
	
	HashMap<Long,MessageFormat> messages;
	int c_class;
	MessageFormat c_message;
	MessageField c_field;
	public boolean checked;
	public int noClass;
	public int noName;
	public int noId;
	public int noTypeField;
	public int noUnitField;
	public int noNameField;
	
	public MessageParser()
	{
		super();
		messages=new HashMap<Long,MessageFormat>();		
	}
	
	public MessageParser(HashMap<Long,MessageFormat> messages)
	{
			super();
			this.messages=messages;
	}
	
	public HashMap<Long,MessageFormat> messageFormat() {return messages;}
	
	@Override
	public void startDocument() throws SAXException {
		checked=false;
		noClass=0;
		noName=0;
		noId=0;
		noTypeField=0;
		noUnitField=0;
		noNameField=0;
		
		super.startDocument();
	}

	@Override
	public void endDocument() throws SAXException {
		super.endDocument();
		
		Collection<MessageFormat> c=messages.values();
		MessageField f;
		for (MessageFormat m : c)
		{
			if (m.cId==-1) { m.noClass=true; noClass++;}
			if (m.mId==-1) {m.noId=true; noId++;}
			if (m.name==null) {m.noName=true; noName++;}
			for (int i=0;i<m.fields.size();i++)
			{
				f=m.fields.get(i);
				if (f.name==null) {f.noName=true; m.noNameField++; noNameField++;}
				if (f.unit==null) {f.noUnit=true; m.noUnitField++; noUnitField++;}
				if (f.type==-1) {f.noType=true; m.noUnitField++; noTypeField++;}
			} 
		}
		checked=true;
	}

	@Override
	public void startElement(String uri, String localName, String qName, Attributes att) throws SAXException {
		super.startElement(uri, localName, qName, att);
		
		String s;
		
		if (qName.equalsIgnoreCase("class"))
		{
			s=att.getValue("name");
			int i=0; while (i<mClasses.length && !s.equalsIgnoreCase(mClasses[i])) i++;
			if (i<mClasses.length) c_class=i;
			else c_class=-1;
			
		}
		else if (qName.equalsIgnoreCase("message"))
		{
			c_message=new MessageFormat(c_class,
					(att.getIndex("ID")>0)?Integer.decode(att.getValue("ID")):
					(att.getIndex("id")>0)?Integer.decode(att.getValue("id")):0,
					att.getValue("name"));
		}
		else if (qName.equalsIgnoreCase("field"))
		{
			 c_field=new MessageField(att.getValue("name"),
					 att.getValue("type"),
					 att.getValue("unit"));
		}
		
	}

	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		super.endElement(uri, localName, qName);
		
		if (qName.equalsIgnoreCase("class"))
		{
			c_class=-1;
		}
		else if (qName.equalsIgnoreCase("message"))
		{
			messages.put(c_class*0x100000000l+c_message.mId, c_message);
		}
		else if (qName.equalsIgnoreCase("field"))
		{
			c_message.addField(c_field);
		}

	}

}
